/**
 * Copyright 2011 Mathieu Magnaudet
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package edu.enac.geoapp.services;

import java.io.File;
import java.net.MalformedURLException;

import org.geotools.feature.FeatureCollection;
import org.geotools.feature.FeatureCollections;
import org.geotools.feature.simple.SimpleFeatureBuilder;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.geometry.jts.JTSFactoryFinder;
import org.geotools.map.DefaultMapLayer;
import org.geotools.map.MapLayer;
import org.geotools.styling.ExternalGraphic;
import org.geotools.styling.Graphic;
import org.geotools.styling.PointSymbolizer;
import org.geotools.styling.SLD;
import org.geotools.styling.Style;
import org.geotools.styling.StyleBuilder;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.referencing.crs.CoordinateReferenceSystem;

import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.Point;

/**
 * Provides a {@link MapLayer} displaying the aircraft position.
 * Implements the singleton pattern
 * @author mathieu
 *
 */
public class AircraftLayerProvider {
	private static final AircraftLayerProvider INSTANCE = new AircraftLayerProvider();
	private double lat;
	private double lon;
	private Point position;
	private CRSProvider crsProvider = CRSProvider.getInstance();
	private final File img = new File("data/Avion_silhouette2.png");

	private static GeometryFactory geometryFactory = JTSFactoryFinder
			.getGeometryFactory(null);

	private AircraftLayerProvider() {

	}

	/**
	 * 
	 * @return the isntance of the provider
	 */
	protected static AircraftLayerProvider getInstance() {
		return INSTANCE;
	}

	/**
	 * Returns the layer
	 * @param rotated if true the layer should be oriented along the aiplane axis (NOT IMPLEMENTED) 
	 * @return the layer
	 * @throws MalformedURLException
	 */
	protected MapLayer getLayer(boolean rotated) throws MalformedURLException {
		updateData();
		CoordinateReferenceSystem crs = rotated ? crsProvider.getRotatedCRS()
				: crsProvider.getStandardCRS();
		SimpleFeatureTypeBuilder builder = new SimpleFeatureTypeBuilder();
		builder.setName("aircraft");
		builder.setCRS(crs);
		builder.add("aircraft_position",
				com.vividsolutions.jts.geom.Point.class);

		final SimpleFeatureType aircraft = builder.buildFeatureType();

		SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(aircraft);
		FeatureCollection<SimpleFeatureType, SimpleFeature> collection = FeatureCollections
				.newCollection();
		featureBuilder.add(position);
		SimpleFeature feature = featureBuilder.buildFeature(null);
		collection.add(feature);
		return new DefaultMapLayer(collection, createPointStyle());
	}

	private Style createPointStyle() throws MalformedURLException {
		StyleBuilder styleBuilder = new StyleBuilder();
		PointSymbolizer pointSymbolizer = styleBuilder.createPointSymbolizer();

		Graphic graphic = styleBuilder.createGraphic();
		ExternalGraphic external = styleBuilder.createExternalGraphic(img.toURI().toURL(), "image/png");
		graphic.graphicalSymbols().add(0, external);

		pointSymbolizer.setGraphic(graphic);

		return SLD.wrapSymbolizers(pointSymbolizer);
	}

	private void updateData() {
		position = geometryFactory.createPoint(new Coordinate(lat, lon));
	}

	/**
	 * @param lat
	 *            the latitude to set
	 */
	public void setLat(double lat) {
		this.lat = lat;
	}

	/**
	 * @return the latitude
	 */
	public double getLat() {
		return lat;
	}

	/**
	 * @param lon
	 *            the longitude to set
	 */
	public void setLon(double lon) {
		this.lon = lon;
	}

	/**
	 * @return the longitude
	 */
	public double getLon() {
		return lon;
	}
}
